//class that represent a vector of bits
//in the implementation it is based on word32 and C++ vector
//Hence it is optimized for many bits and also for adding more bits dynamically

#include "BitVector32.h"

//constructor that takes a binary string as input
//the size of the vector will be equal to the length of the string
//it is assumed that least significant bit first in the string
BitVector32::BitVector32(std::string initString){
  nbrOfBits=initString.size();
  nbrOfWords=((nbrOfBits-1)>>5)+1;
  bitVec.resize(nbrOfWords);
  for(unsigned i=0;i<nbrOfBits;i++){
    if(initString[i]=='1')
       setBit(i);
  }    
}

//converts the bitVector to a string 
//binary representation, LSB first
std::string BitVector32::toBinStringLSB(){
  std::string s="";
  for(unsigned k=0;k<nbrOfBits;k++){
    if(getBit(k)==0)
      s+="0";
    else
      s+="1";
  }
  return s;  
}

//converts the bitVector to a string 
//binary representation, MSB first
std::string BitVector32::toBinStringMSB(){
  std::string s="";
  for(unsigned k=1;k<=nbrOfBits;k++){
    if(getBit(nbrOfBits-k)==0)
      s+="0";
    else
      s+="1";
  }
  return s;
}

//converts the bitVector to a string 
//hexadecimal representation, LSB first
std::string BitVector32::toHexStringLSB(){
  std::string s=""; 
  for(unsigned i=0;i<(nbrOfWords-1);i++){
    s+=bitVec[i].toHexStringLSB();
    s+=" ";
  }
  //take care of final word
  unsigned long bitsInLastWord=nbrOfBits-((nbrOfWords-1)<<5);
  int symbolsW=0;
  if(bitsInLastWord>0)
    symbolsW=((bitsInLastWord-1)>>2)+1; 
  std::string tempS=bitVec[nbrOfWords-1].toHexStringLSB();  
  for(int i=0;i<symbolsW;i++){
    s+=tempS[i];
  }
  
  return s;
}

//converts the bitVector to a string 
//hexadecimal representation, MSB first
std::string BitVector32::toHexStringMSB(){
  std::string s="";
 
  //start to output final word
  //calcultae how many hexadecimal symbols that are valid
  //then extract those symbols from highest word
  unsigned long bitsInLastWord=nbrOfBits-((nbrOfWords-1)<<5);
  int symbolsW=0;
  if(bitsInLastWord>0)
    symbolsW=((bitsInLastWord-1)>>2)+1;
  std::string tempS=bitVec[nbrOfWords-1].toHexStringMSB();
  for(int i=0;i<symbolsW;i++){
   s+=tempS[8-symbolsW+i];
  }
  for(unsigned i=1;i<=(nbrOfWords-1);i++){
   s+=" ";
    s+=bitVec[nbrOfWords-1-i].toHexStringMSB();
   
  }
  return s;
}

//append a bit to the end of the vector
void BitVector32::appendBit(int val){
  //check if we need to add new word to the vector
  if((nbrOfBits & 0x1f)==0){
    word32 w(val);
    bitVec.push_back(w);
    nbrOfBits++;
    nbrOfWords++;
  }
  //no new word needed
  else{
    bitVec[nbrOfWords-1].setVal(nbrOfBits,val);
    nbrOfBits++;
  }
}

//append a word to the end of the vector
void BitVector32::appendWord32(word32 w){
  //check if bits left before new word is appended
  int bitsLeft=nbrOfBits & 0x1f;
  //all bits in new word
  if(bitsLeft==0){
    bitVec.push_back(w);
    nbrOfBits+=32;
    nbrOfWords++; 
  }
  else{
    //some bits in old word rest in new
    unsigned long mask=0xFFFFFFFFuL >> bitsLeft;
    word32 wMask(mask);
    word32 temp(w);
    temp.andOp(wMask);
    temp.lshift(bitsLeft);
    bitVec[nbrOfWords-1].orOp(temp);
    //add new word
    temp.assign(w);
    temp.rshift(32-bitsLeft);
    bitVec.push_back(temp);
    nbrOfBits+=32;
    nbrOfWords++;
  }
}


